package com.nengchuan.eic.nceconomy.component.template;

import com.nengchuan.eic.nceconomy.entity.po.TemplateDic;
import com.nengchuan.eic.nceconomy.entity.po.TemplateSheet;
import com.nengchuan.eic.nceconomy.util.ExcelSerialNumUtils;
import com.nengchuan.eic.nceconomy.util.IdSequence;
import com.nengchuan.util.NullCheckUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 处理辅助类
 */
@Component("templateHandlerSupport")
public class HandlerSupport {
    private static List<String> nameList= Arrays.asList("【甲供设备】","【甲供材料】");
    private static List<String> parentList= Arrays.asList("建筑工程","安装工程");

    /**
     * 创建excel数据对象
     * @param metaData  解析的原始数据
     * @param response  封装的响应对象
     * @param fieldIdxEnd 字段结束下标
     * @param lineIndxIdxEnd 行指标下标
     */
    public  void createTemplateDic(List<String[]> metaData,
                                      ResponseModel response,
                                      String sheetName,
                                      int fieldIdxEnd,
                                      int lineIndxIdxEnd) {
        //读取标题抬头等信息
        List<TemplateDic> templateDics=setTitle(metaData);

        //读取所有的行指标,如果有多行合并成一行 以"-"为分隔符
        setFieldAndGetIndexMap(templateDics,metaData,fieldIdxEnd);

//        //存储所有数据
        setData(templateDics,metaData,sheetName,fieldIdxEnd+1,lineIndxIdxEnd);

        response.setTemplateDics(templateDics);
    }


    /**
     * 创建excelsheet对象
     * @param sheetName sheet名
     * @param order 排序字段记录
     * @return
     */
    public TemplateSheet createTemplateSheet(String sheetName, int order) {
        return TemplateSheet.builder().sheetName(sheetName).sequence(order).delFlag(0).build();
    }

    /**
     * 设置数据
     * @param templateDics 存储PO对象的容器
     * @param metaData 解析的原始对象集合
     * @param fieldIdxEnd 字段的结束下标,也就是非模板数据的起始坐标
     * @param lineIndxIdxEnd 行指标结束地址
     */
    private  void setData(List<TemplateDic> templateDics,
                                List<String[]> metaData,
                                String sheetName,
                                int fieldIdxEnd,
                                int lineIndxIdxEnd) {

        //获取数据的起始下标
        if(fieldIdxEnd>=metaData.size()){
            return;
        }

        List<TemplateDic> historySerialNum=new ArrayList<>(metaData.size()-fieldIdxEnd);
        int order= getNewestOrder(templateDics);

        for (int i = fieldIdxEnd; i <metaData.size() ; i++) {
            String[] datas=metaData.get(i);

            for (int j = 0; j <=lineIndxIdxEnd ; j++) {
                String data=datas[j];
                //存储序号,并分辨序号上下级关系
                if(j==0){
                    if(sheetName.contains("主要设备材料汇总表")){
                        setSeq(templateDics,historySerialNum,sheetName, data,order, i,datas[j+1]);
                    }else{
                        setSeq(templateDics,historySerialNum,sheetName, data,order, i);
                    }
                    order= getNewestOrder(templateDics);
                    continue;
                }

                TemplateDic templateDic=TemplateDic
                        .builder()
                        .id(IdSequence.generateId())
                        .lineStartCoordinates(i)
                        .lineEndCoordinates(i)
                        .rowStartCoordinates(j)
                        .rowEndCoordinates(j)
                        .sequence(order++)
                        .value(data)
                        .delFlag(0)
                        .build();
                templateDics.add(templateDic);
            }

        }
    }


    /**
     * 获取集合中最新的排序字段
     * @param templateDics
     * @return
     */
    private  Integer getNewestOrder(List<TemplateDic> templateDics) {
        return templateDics.size()>0?templateDics.get(templateDics.size() - 1).getSequence()+1:0;
    }

    /**
     * 设置序号
     * @param templateDics PO对象集合
     * @param order 排序字段
     * @param i 下标
     * @param seq 序号
     * @return
     */
    private  void setSeq(List<TemplateDic> templateDics,
                              List<TemplateDic> history,
                              String sheetName,
                              String seq,
                              int order,
                              int i) {

        TemplateDic templateDic=TemplateDic
                .builder()
                .id(IdSequence.generateId())
                .lineStartCoordinates(i)
                .lineEndCoordinates(i)
                .rowStartCoordinates(0)
                .rowEndCoordinates(0)
                .sequence(order++)
                .value(seq)
                .delFlag(0)
                .build();

        Long parentId;
        if((NullCheckUtils.isNull(seq)||ExcelSerialNumUtils.isDownSeq(seq))&&(sheetName.contains("建筑单位工程汇总表")||
                sheetName.contains("安装单位工程汇总表")||
                sheetName.contains("架空输电线路工程单位工程汇总表")||sheetName.contains("主要设备材料汇总表")||sheetName.contains("建筑安装工程施工费用结算一览表")||
                sheetName.contains("辅助费用表")|| sheetName.contains("安装工程施工费用结算一览表"))){
            parentId=ExcelSerialNumUtils.getParentSequenceTable3(history,templateDic);
        }else{
            parentId=ExcelSerialNumUtils.getParentSequence(history,templateDic);
        }
        templateDic.setParentId(parentId);
        templateDics.add(templateDic);
    }

    /**
     * 设置序号
     * @param templateDics PO对象集合
     * @param order 排序字段
     * @param i 下标
     * @param seq 序号
     * @return
     */
    private  void setSeq(List<TemplateDic> templateDics,
                         List<TemplateDic> history,
                         String sheetName,
                         String seq,
                         int order,
                         int i,String name) {

        TemplateDic templateDic=TemplateDic
                .builder()
                .id(IdSequence.generateId())
                .lineStartCoordinates(i)
                .lineEndCoordinates(i)
                .rowStartCoordinates(0)
                .rowEndCoordinates(0)
                .sequence(order++)
                .value(seq)
                .delFlag(0)
                .build();

        if(nameList.contains(name)){
            templateDics.add(templateDic);
            return;
        }
        Long parentId=null;
        if((NullCheckUtils.isNull(seq)||ExcelSerialNumUtils.isDownSeq(seq))&&(sheetName.contains("建筑单位工程汇总表")||
                sheetName.contains("安装单位工程汇总表")||
                sheetName.contains("架空输电线路工程单位工程汇总表")||sheetName.contains("主要设备材料汇总表")||sheetName.contains("建筑安装工程施工费用结算一览表")||
                sheetName.contains("辅助费用表")|| sheetName.contains("安装工程施工费用结算一览表"))){
            //如果序号为大写数字或为空,则它们本身为顶级节点
            if(parentList.contains(name)){
                history.add(templateDic);
            }else{
                if(NullCheckUtils.isNull(seq)||ExcelSerialNumUtils.isDownSeq(seq)){
                    for (int j = history.size() - 2; j >= 0; j--) {
                        String tempSeq=history.get(j).getValue();
                        if(NullCheckUtils.isNotNull(tempSeq)){
                            parentId= history.get(j).getId();
                        }
                    }
                }
            }
        }else{
            parentId=ExcelSerialNumUtils.getParentSequence(history,templateDic,sheetName);
        }
        templateDic.setParentId(parentId);
        templateDics.add(templateDic);
    }
    /**
     * 获取标题、抬头等信息
     * @param metaData 解析的原始数据
     * @return
     */
    private  List<TemplateDic> setTitle(List<String[]> metaData){
        int order=0;

        //获取标题与数据的分割下标
        int segmentIndex=getTitleAndDataSegmentIndex(metaData);

        List<TemplateDic> templateDics=new ArrayList<>();
        //如果分割下标小于1，则代表没有标题信息
        if(segmentIndex<1){
            return templateDics;
        }

        for (int i = 0; i <segmentIndex ; i++) {
            String[] str=metaData.get(i);
            for (int j = 0; j < str.length; j++) {
                String val=str[j];
                TemplateDic single;
                if(NullCheckUtils.isNull(val)){
                    //横向向前寻找第一个不为空的元素,并将自己的坐标设置到不为空元素的结束坐标上
                    single=getLastTemplateDic(templateDics);


                    //如果最后一个对象不为空,并且对象的行坐标包含当前坐标,则将当前坐标值设置到结尾坐标
                    if(single!=null&&
                            (single.getLineStartCoordinates()<=i&&single.getLineEndCoordinates()>=i)){
                        int newRowEnd=single.getRowEndCoordinates()<j?j:single.getRowEndCoordinates();
                        single.setRowEndCoordinates(newRowEnd);
                        continue;
                    }
                }else{
                    single=TemplateDic
                            .builder()
                            .id(IdSequence.generateId())
                            .lineStartCoordinates(i)
                            .lineEndCoordinates(i)
                            .rowStartCoordinates(j)
                            .rowEndCoordinates(j)
                            .sequence(order++)
                            .value(val)
                            .delFlag(0)
                            .build();
                    templateDics.add(single);
                }
            }
        }
        return templateDics;
    }

    /**
     * 获取可用长度
     * @param metadata
     * @param startIdx
     * @param endIdx
     * @return
     */
    private int getUsableSize(List<String[]> metadata,int startIdx,int endIdx){
        int usableSize=Integer.MAX_VALUE;
        int tempSize;
        for (int i = startIdx; i <=endIdx; i++) {
            tempSize=metadata.get(i).length;
            if(tempSize<usableSize){
                usableSize=tempSize;
            }
        }
        return usableSize;
    }

    /**
     * 获取前驱不为空的节点
     * @param data
     * @param endIdx
     * @return
     */
    private String getPrecursorNode(String[] data,int endIdx){
        for (int i = endIdx - 1; i >= 0; i--) {
            if(NullCheckUtils.isNotNull(data[i])){
                return data[i];
            }
        }
        return "";
    }

    /**
     * 设置行字段
     * @param allData 所有解析数据
     * @param metadata 元数据
     * @param endIdx 行字段截止下标
     */
    private void setFieldAndGetIndexMap(List<TemplateDic> allData, List<String[]> metadata, int endIdx){
        //获取字段的起始下标
        int startIdx=getTitleAndDataSegmentIndex(metadata);

        if(startIdx<0||endIdx>=metadata.size()){
            return;
        }
        int usableSize=getUsableSize(metadata,startIdx,endIdx);
        List<TemplateDic> templateDics=new ArrayList<>(usableSize);
        TemplateDic templateDic;
        String bucketData;
        boolean isEmpty;
        String tempData;
        for (int i = 0; i < usableSize; i++) {
            bucketData="";
            isEmpty=true;
            for (int j = endIdx; j >= startIdx; j--) {
                tempData=metadata.get(j)[i];
                if(!isEmpty){
                    if(NullCheckUtils.isNull(tempData)){
                        tempData=getPrecursorNode(metadata.get(j),i);
                    }
                }

                if(NullCheckUtils.isNotNull(tempData)){
                    isEmpty=false;
                    tempData=NullCheckUtils.isNull(bucketData)?tempData:tempData+"-"+bucketData;
                }
                bucketData=tempData;

            }
            if(NullCheckUtils.isNull(bucketData)&&templateDics.size()>0){
                templateDic=templateDics.get(templateDics.size()-1);
                templateDic.setRowEndCoordinates(i);
            }else{
                String[] vals = splitUnit(bucketData);
                templateDic = TemplateDic
                        .builder()
                        .id(IdSequence.generateId())
                        .lineStartCoordinates(startIdx)
                        .lineEndCoordinates(endIdx)
                        .rowStartCoordinates(i)
                        .rowEndCoordinates(i)
                        .value(vals[0])
                        .unit(vals[1])
                        .delFlag(0)
                        .build();
            }
            templateDics.add(templateDic);

        }

        AtomicInteger order= new AtomicInteger(getNewestOrder(allData));
        templateDics.forEach(e->e.setSequence(order.getAndIncrement()));
        allData.addAll(templateDics);
    }

    /**
     * 获取具有相同前缀val的元素下标
     * @param templateDics
     * @param prefix
     * @return
     */
    private int getLastIncludePrefixIndex(List<TemplateDic> templateDics,String prefix){
        String value;
        for (int i = templateDics.size() - 1; i >= 0; i--) {
            value=templateDics.get(i).getValue();
            if(NullCheckUtils.isNotNull(value)&&value.contains(prefix)){
                return i;
            }
        }
        return templateDics.size();
    }

    /**
     * 获取包含当前列的对象下标
     * @param params
     * @param idx
     * @return
     */
    private  int getIncludeCurrRowBean(List<TemplateDic> params,int idx){
        for (int i = 0; i <params.size(); i++) {
            TemplateDic templateDic=params.get(i);
            if(templateDic.getRowStartCoordinates()<=idx&&templateDic.getRowEndCoordinates()>=idx){
                return i;
            }
        }

        return -1;
    }


    /**
     * 获取标题与实际数据的分割下标
     * @param params
     * @return
     */
    private  int getTitleAndDataSegmentIndex(List<String[]> params){
        for (int i = 0; i < params.size(); i++) {
            String[] strs=params.get(i);
            if(strs.length>0&&"序号".equals(strs[0])||"编号".equals(strs[0])){
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取集合中最后一个对象
     * @param templateDics
     * @return
     */
    private  TemplateDic getLastTemplateDic(List<TemplateDic> templateDics){
        return NullCheckUtils.isNull(templateDics)?null:templateDics.get(templateDics.size()-1);
    }


    /**
     * 为字符串拆分单位
     * @param val
     * @return
     */
    private  String[] splitUnit(String val){
        String leftBracket="(";
        String rightBracket=")";

        String[] result=new String[2];
        boolean flag=val.contains(leftBracket)&&val.contains(rightBracket);
        if(flag){
            int leftIndex=val.indexOf(leftBracket);
            int rightIndex=val.lastIndexOf(rightBracket);
            String str1=val.substring(0,leftIndex);
            String str2=val.substring(leftIndex+1,rightIndex);
            result[0]=str1;
            result[1]=str2;
        }else{
            result[0]=val;
            result[1]=null;
        }
        return result;
    }
}
